1 /*
2 * Copyright 2002-2013 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.springframework.test.context.junit4.spr9051;
18
19 import javax.sql.DataSource;
20
21 import org.junit.Before;
22
23 import org.springframework.context.annotation.Bean;
24 import org.springframework.context.annotation.Configuration;
25 import org.springframework.jdbc.core.JdbcTemplate;
26 import org.springframework.jdbc.datasource.DataSourceTransactionManager;
27 import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
28 import org.springframework.test.context.ContextConfiguration;
29 import org.springframework.test.context.transaction.AfterTransaction;
30 import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
31 import org.springframework.tests.sample.beans.Employee;
32 import org.springframework.transaction.PlatformTransactionManager;
33
34 import static org.junit.Assert.*;
35
36 /**
37 * Concrete implementation of {@link AbstractTransactionalAnnotatedConfigClassTests}
38 * that does <b>not</b> use a true {@link Configuration @Configuration class} but
39 * rather a <em>lite mode</em> configuration class (see the Javadoc for {@link Bean @Bean}
40 * for details).
41 *
42 * @author Sam Brannen
43 * @since 3.2
44 * @see Bean
45 * @see TransactionalAnnotatedConfigClassWithAtConfigurationTests
46 */
47 @ContextConfiguration(classes = TransactionalAnnotatedConfigClassesWithoutAtConfigurationTests.AnnotatedFactoryBeans.class)
48 public class TransactionalAnnotatedConfigClassesWithoutAtConfigurationTests extends
49 AbstractTransactionalAnnotatedConfigClassTests {
50
51 /**
52 * This is intentionally <b>not</b> annotated with {@code @Configuration}.
53 *
54 * <p>Consequently, this class contains <i>annotated factory bean methods</i>
55 * instead of standard singleton bean methods.
56 */
57 // @Configuration
58 static class AnnotatedFactoryBeans {
59
60 @Bean
61 public Employee employee() {
62 Employee employee = new Employee();
63 employee.setName("John Smith");
64 employee.setAge(42);
65 employee.setCompany("Acme Widgets, Inc.");
66 return employee;
67 }
68
69 @Bean
70 public PlatformTransactionManager transactionManager() {
71 return new DataSourceTransactionManager(dataSource());
72 }
73
74 /**
75 * Since this method does not reside in a true {@code @Configuration class},
76 * it acts as a factory method when invoked directly (e.g., from
77 * {@link #transactionManager()}) and as a singleton bean when retrieved
78 * through the application context (e.g., when injected into the test
79 * instance). The result is that this method will be called twice:
80 *
81 * <ol>
82 * <li>once <em>indirectly</em> by the {@link TransactionalTestExecutionListener}
83 * when it retrieves the {@link PlatformTransactionManager} from the
84 * application context</li>
85 * <li>and again when the {@link DataSource} is injected into the test
86 * instance in {@link AbstractTransactionalAnnotatedConfigClassTests#setDataSource(DataSource)}.</li>
87 *</ol>
88 *
89 * Consequently, the {@link JdbcTemplate} used by this test instance and
90 * the {@link PlatformTransactionManager} used by the Spring TestContext
91 * Framework will operate on two different {@code DataSource} instances,
92 * which is almost certainly not the desired or intended behavior.
93 */
94 @Bean
95 public DataSource dataSource() {
96 return new EmbeddedDatabaseBuilder()//
97 .addScript("classpath:/org/springframework/test/context/junit4/spr9051/schema.sql")//
98 // Ensure that this in-memory database is only used by this class:
99 .setName(getClass().getName())//
100 .build();
101 }
102
103 }
104
105
106 @Before
107 public void compareDataSources() throws Exception {
108 // NOTE: the two DataSource instances are NOT the same!
109 assertNotSame(dataSourceFromTxManager, dataSourceViaInjection);
110 }
111
112 /**
113 * Overrides {@code afterTransaction()} in order to assert a different result.
114 *
115 * <p>See in-line comments for details.
116 *
117 * @see AbstractTransactionalAnnotatedConfigClassTests#afterTransaction()
118 * @see AbstractTransactionalAnnotatedConfigClassTests#modifyTestDataWithinTransaction()
119 */
120 @AfterTransaction
121 @Override
122 public void afterTransaction() {
123 assertEquals("Deleting yoda", 1, deletePerson(YODA));
124
125 // NOTE: We would actually expect that there are now ZERO entries in the
126 // person table, since the transaction is rolled back by the framework;
127 // however, since our JdbcTemplate and the transaction manager used by
128 // the Spring TestContext Framework use two different DataSource
129 // instances, our insert statements were executed in transactions that
130 // are not controlled by the test framework. Consequently, there was no
131 // rollback for the two insert statements in
132 // modifyTestDataWithinTransaction().
133 //
134 assertNumRowsInPersonTable(2, "after a transactional test method");
135 }
136
137 }